/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       sphericaljoint.cpp
 * Author:     karooolek
 * Created on: Nov 14, 2009
 *
 **********************************************************************************************************************/

#include "sphericaljoint.h"

namespace mGameEngine
{

namespace Physics
{

SphericalJoint::SphericalJoint(    const Vector3 &point1,
                                const Vector3 &point2,
                                const Vector3 &axis1,
                                const Vector3 &axis2,
                                float maxTwist, float maxSwing) :
    RevoluteJoint(point1, point2, axis1, axis2, maxTwist),
    _maxSwing(maxSwing)
{
}

SphericalJoint::~SphericalJoint()
{
    // everything done in ~Joint()
}

void SphericalJoint::setMaximalSwing(float maxSwing)
{
    // maxmial swing less than 180 degrees
    if(maxSwing < 0.0f || maxSwing > M_PI)
    {
        return;
    }

    _maxSwing = maxSwing;

    if(_joint)
    {
        // TODO
    }
}

void SphericalJoint::create(NxActor *actor1, NxActor *actor2) const
{
    // two actors required
    if(!actor1 || !actor2)
    {
        return;
    }

    // already created
    if(_created)
    {
        return;
    }

    // create joint
    NxSphericalJointDesc desc;

    // assign first actor
    if(actor1->isDynamic())
    {
        desc.actor[0] = actor1;
        desc.localNormal[0] = NxVec3(_anchor1.m[2]);
        desc.localAxis[0] = NxVec3(_anchor1.m[0]);
        desc.localAnchor[0] = NxVec3(_anchor1.m[3]);
    }
    else
    {
        desc.actor[0] = NULL;
        desc.localNormal[0] = actor1->getGlobalOrientation() * NxVec3(_anchor1.m[2]);
        desc.localAxis[0] = actor1->getGlobalOrientation() * NxVec3(_anchor1.m[0]);
        desc.localAnchor[0] = actor1->getGlobalPose() * NxVec3(_anchor1.m[3]);
    }

    // assign second actor
    if(actor2->isDynamic())
    {
        desc.actor[1] = actor2;
        desc.localNormal[1] = -NxVec3(_anchor2.m[2]);
        desc.localAxis[1] = -NxVec3(_anchor2.m[0]);
        desc.localAnchor[1] = NxVec3(_anchor2.m[3]);
    }
    else
    {
        desc.actor[1] = NULL;
        desc.localNormal[1] = actor2->getGlobalOrientation() * -NxVec3(_anchor2.m[2]);
        desc.localAxis[1] = actor2->getGlobalOrientation() * -NxVec3(_anchor2.m[0]);
        desc.localAnchor[1] = actor2->getGlobalPose() * NxVec3(_anchor2.m[3]);
    }

    if(_maxTwist < M_PI)
    {
        desc.flags |= NX_SJF_TWIST_LIMIT_ENABLED;
        desc.twistLimit.low.value = -_maxTwist;
        desc.twistLimit.high.value = _maxTwist;
    }

    if(_maxSwing < M_PI)
    {
        desc.flags |= NX_SJF_SWING_LIMIT_ENABLED;
        desc.swingLimit.value = _maxSwing;
    }

    _joint = actor1->getScene().createJoint(desc);

    // problems while creating joint
    if(_joint == NULL)
    {
        return;
    }

    // joint is created
    _created = true;
}

}
}

